package com.laijiale.Service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.SecureUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.laijiale.mapper.EmpMapper;
import com.laijiale.mapper.PermissionMapper;
import com.laijiale.mapper.RoleMapper;
import com.laijiale.Service.EmpService;
import com.laijiale.VO.LoginVO;
import com.laijiale.dto.*;
import com.laijiale.entities.Emp;
import com.laijiale.entities.EmpRole;
import com.laijiale.entities.Role;
import com.laijiale.exception.ServiceException;
import com.laijiale.util.JwtUtil;
import com.laijiale.util.MinioUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;
import java.util.List;

/**
 * @author laijiale
 * @date 2024年07月29日 15:32
 */
@Service
@CacheConfig(cacheNames = "emp")
public class EmpServiceImpl implements EmpService {
    @Autowired
    private EmpMapper empMapper;
    @Autowired
    private RoleMapper roleMapper;


    @Autowired
    private PermissionMapper permissionMapper;


    @CacheEvict(allEntries = true)
    @Override
    public int insert(EmpInsertDTO dto) {
        Emp emp = BeanUtil.copyProperties(dto, Emp.class);
        // 密码加密
        emp.setPassword(SecureUtil.md5(emp.getPassword()));
        // 设置默认值
        String idcard = emp.getIdcard();
        emp.setAvatar("default-avatar.png");
        emp.setGender(IdcardUtil.getGenderByIdCard(idcard));
        emp.setAge(IdcardUtil.getAgeByIdCard(idcard));
        emp.setProvince(IdcardUtil.getProvinceByIdCard(idcard));
        emp.setAddress("暂未添加详细住址");
        emp.setInfo("暂未添加详细介绍");
        emp.setDeleted(0);
        emp.setCreated(LocalDateTime.now());
        emp.setUpdated(LocalDateTime.now());
        int result = empMapper.insert(emp);
        if (result <= 0) {
            throw new ServiceException("DB添加失败");
        }
        return result;
    }

    @Cacheable(key = "#id", condition = "#id !=null", unless = " #result==null")
    @Override
    public Emp selectById(Long id)
    {
        Emp result = empMapper.selectById(id);
        if (ObjectUtil.isNull(result)) {
            throw new ServiceException("ID不存在");
        }
        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(allEntries = true)
    @Override
    public int updateById(EmpUpdateDTO empUpdateDTO) {
            Emp emp = BeanUtil.copyProperties(empUpdateDTO, Emp.class);
            emp.setCreated(null);
            emp.setUpdated(LocalDateTime.now());
            int result = empMapper.updateById(emp);
            if (result <= 0) {
                throw new ServiceException("DB修改失败");
            }
            return result;
    }

    @CacheEvict(allEntries = true)
    @Override
    public int logicDeleteById(Long id) {
            //todo 查询记录是否被引用
            int result = empMapper.logicDeleteById(id);
            if (result <= 0) {
                throw new ServiceException("DB逻辑删除失败");
            }
            return result;
    }


    @CacheEvict(allEntries = true)
    @Override
    public int logicDeleteByIds(List<Long> ids) {
            //todo 查询记录是否被引用
            int result = empMapper.logicDeleteByIds(ids);
            if (result <= 0) {
                throw new ServiceException("DB逻辑批删失败");

            }
            return result;
    }

    @Cacheable(key = "#root.methodName",unless = "#result==null")
    @Override
    public List<Emp> list() {

            return empMapper.list();
        }


    @Cacheable(key = "#root.methodName + ':' + " +
            "#pageDTO.getPageNum()+':' + " +
            "#pageDTO.getPageSize()",unless = "#result == null ")
    @Override
    public PageInfo<Emp> page(PageDTO pageDTO) {
            PageHelper.startPage(pageDTO.getPageNum(), pageDTO.getPageSize());

            List<Emp> list = empMapper.list();
            PageInfo<Emp> pageInfo = new PageInfo(list);

            return pageInfo;
    }

    @Override
    public LoginVO loginByAccount(LoginDTO dto) {
        String username = dto.getUsername();
        String password = SecureUtil.md5(dto.getPassword());
         Emp emp=empMapper.selectByAccount(username,password);
        if (ObjectUtil.isNotNull(emp)){
            String token = JwtUtil.build(emp.getId(),emp.getRealname(),emp.getAvatar());
            LoginVO loginVO = new LoginVO();
            loginVO.setToken(token);
            loginVO.setPermissions(permissionMapper.selectByEmpId(emp.getId()));
            loginVO.setEmp(emp);
            return loginVO;
        }else {
            throw new ServiceException("账号或密码错误");
        }
    }

    @Cacheable(key = "#root.methodName + ':' + " +
            "#dto.getRealname() + ':' + " +
            "#dto.getPageNum() + ':' +" +
            "#dto.getPageSize()",unless = "#result==null")
    @Override
    public PageInfo<Emp> pageLikeRealname(EmpPageDTO dto) {
        PageHelper.startPage(dto.getPageNum(),dto.getPageSize());
        return new PageInfo<>(empMapper.pageLikeRealname(dto.getRealname()));
    }
    @CacheEvict(allEntries = true)
    @Override
    public String uploadAvatar(EmpUploadDTO dto) {
        //将文件上传在MINIO中
        final String DIR="test";
        final String BUCKET_NAME="start";
        MultipartFile avatarFile=dto.getAvatarFile();
        Long id=dto.getId();
        //DB查询
        Emp emp =empMapper.selectById(id);
        if (ObjectUtil.isNull(emp)){
            throw new ServiceException("员工不存在");
        }
        //从MINIO中删除旧文件，默认头像不删除
        String oldAvatar = emp.getAvatar();
        if (!("default-avatar.png".equals(oldAvatar))){
            MinioUtil.delete(oldAvatar,DIR,BUCKET_NAME);
        }
        //新文件上传到MINIO中
        String newAvatar= MinioUtil.randomFilename(avatarFile);
        MinioUtil.upload(avatarFile,newAvatar,DIR,BUCKET_NAME);
        // DB修改

        emp.setAvatar(newAvatar);
        if (empMapper.updateById(emp) <= 0) {
            throw new ServiceException("DB修改失败");
        }
        return newAvatar;
    }
    @CacheEvict(allEntries = true)
    @Override
    public String resetPassword(Long id) {
        String newPassword="123456789";
        Emp emp=new Emp();
        emp.setId(id);
        emp.setPassword(SecureUtil.md5(newPassword));
        emp.setUpdated(LocalDateTime.now());
        if (empMapper.updateById(emp)<=0){
            throw new ServiceException("密码重置失败");
        }
        return newPassword;
    }
    @Cacheable(key = "#root.methodName+':'+ #id",unless = "#result==null")
    @Override
    public List<Role> getRoles(Long id) {
        return roleMapper.selectByEmpId(id);
    }
    @CacheEvict(allEntries = true)
    @Override
    public int updateRoles(EmpUpdateRolesDTO dto) {
        Long id=dto.getId();
        List<Long> roleIds=dto.getRoleIds();
        //删除该员工全部中间表记录
        roleMapper.logicDeleteByEmpId(id);
        for(Long roleId:roleIds){
            EmpRole empRole =new EmpRole();
            empRole.setFkRoleId(roleId);
            empRole.setFkEmpId(id);
            empRole.setDeleted(0);
            empRole.setCreated(LocalDateTime.now());
            empRole.setUpdated(LocalDateTime.now());
            if (roleMapper.insertEmpRole(empRole)<=0) {
                throw new ServiceException("添加角色失败");


            }

        }
        return 1;
    }

    @Override
    public int updatePassword(EmpUpdatePasswordDTO dto) {
        String oldPassword=SecureUtil.md5(dto.getOldPassword());
        String newPassword=SecureUtil.md5(dto.getNewPassword());
        Long id= dto.getId();
       if (empMapper.updatePassword(newPassword,oldPassword,id)<=0){
           throw new ServiceException("账号或密码错误");
       }
       return 1;
    }
}
